home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / var / lib / python-support / python2.6 / xdg / IconTheme.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  14.5 KB  |  466 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''
  5. Complete implementation of the XDG Icon Spec Version 0.8
  6. http://standards.freedesktop.org/icon-theme-spec/
  7. '''
  8. import os
  9. import sys
  10. import time
  11. from xdg.IniFile import *
  12. from xdg.BaseDirectory import *
  13. from xdg.Exceptions import *
  14. import xdg.Config as xdg
  15.  
  16. class IconTheme(IniFile):
  17.     '''Class to parse and validate IconThemes'''
  18.     
  19.     def __init__(self):
  20.         IniFile.__init__(self)
  21.  
  22.     
  23.     def __repr__(self):
  24.         return self.name
  25.  
  26.     
  27.     def parse(self, file):
  28.         IniFile.parse(self, file, [
  29.             'Icon Theme',
  30.             'KDE Icon Theme'])
  31.         self.dir = os.path.dirname(file)
  32.         (nil, self.name) = os.path.split(self.dir)
  33.  
  34.     
  35.     def getDir(self):
  36.         return self.dir
  37.  
  38.     
  39.     def getName(self):
  40.         return self.get('Name', locale = True)
  41.  
  42.     
  43.     def getComment(self):
  44.         return self.get('Comment', locale = True)
  45.  
  46.     
  47.     def getInherits(self):
  48.         return self.get('Inherits', list = True)
  49.  
  50.     
  51.     def getDirectories(self):
  52.         return self.get('Directories', list = True)
  53.  
  54.     
  55.     def getHidden(self):
  56.         return self.get('Hidden', type = 'boolean')
  57.  
  58.     
  59.     def getExample(self):
  60.         return self.get('Example')
  61.  
  62.     
  63.     def getSize(self, directory):
  64.         return self.get('Size', type = 'integer', group = directory)
  65.  
  66.     
  67.     def getContext(self, directory):
  68.         return self.get('Context', group = directory)
  69.  
  70.     
  71.     def getType(self, directory):
  72.         value = self.get('Type', group = directory)
  73.         if value:
  74.             return value
  75.         return 'Threshold'
  76.  
  77.     
  78.     def getMaxSize(self, directory):
  79.         value = self.get('MaxSize', type = 'integer', group = directory)
  80.         if value or value == 0:
  81.             return value
  82.         return self.getSize(directory)
  83.  
  84.     
  85.     def getMinSize(self, directory):
  86.         value = self.get('MinSize', type = 'integer', group = directory)
  87.         if value or value == 0:
  88.             return value
  89.         return self.getSize(directory)
  90.  
  91.     
  92.     def getThreshold(self, directory):
  93.         value = self.get('Threshold', type = 'integer', group = directory)
  94.         if value or value == 0:
  95.             return value
  96.         return 2
  97.  
  98.     
  99.     def checkExtras(self):
  100.         if self.defaultGroup == 'KDE Icon Theme':
  101.             self.warnings.append('[KDE Icon Theme]-Header is deprecated')
  102.         
  103.         if self.fileExtension == '.theme':
  104.             pass
  105.         elif self.fileExtension == '.desktop':
  106.             self.warnings.append('.desktop fileExtension is deprecated')
  107.         else:
  108.             self.warnings.append('Unknown File extension')
  109.         
  110.         try:
  111.             self.name = self.content[self.defaultGroup]['Name']
  112.         except KeyError:
  113.             self.errors.append("Key 'Name' is missing")
  114.  
  115.         
  116.         try:
  117.             self.comment = self.content[self.defaultGroup]['Comment']
  118.         except KeyError:
  119.             self.errors.append("Key 'Comment' is missing")
  120.  
  121.         
  122.         try:
  123.             self.directories = self.content[self.defaultGroup]['Directories']
  124.         except KeyError:
  125.             self.errors.append("Key 'Directories' is missing")
  126.  
  127.  
  128.     
  129.     def checkGroup(self, group):
  130.         if group == self.defaultGroup:
  131.             pass
  132.         elif group in self.getDirectories():
  133.             
  134.             try:
  135.                 self.type = self.content[group]['Type']
  136.             except KeyError:
  137.                 self.type = 'Threshold'
  138.  
  139.             
  140.             try:
  141.                 self.name = self.content[group]['Name']
  142.             except KeyError:
  143.                 self.errors.append("Key 'Name' in Group '%s' is missing" % group)
  144.             except:
  145.                 None<EXCEPTION MATCH>KeyError
  146.             
  147.  
  148.         None<EXCEPTION MATCH>KeyError
  149.         if not re.match('^\\[X-', group) and group.decode('utf-8', 'ignore').encode('ascii', 'ignore') == group:
  150.             self.errors.append('Invalid Group name: %s' % group)
  151.         
  152.  
  153.     
  154.     def checkKey(self, key, value, group):
  155.         if group == self.defaultGroup:
  156.             if re.match('^Name' + xdg.Locale.regex + '$', key):
  157.                 pass
  158.             elif re.match('^Comment' + xdg.Locale.regex + '$', key):
  159.                 pass
  160.             elif key == 'Inherits':
  161.                 self.checkValue(key, value, list = True)
  162.             elif key == 'Directories':
  163.                 self.checkValue(key, value, list = True)
  164.             elif key == 'Hidden':
  165.                 self.checkValue(key, value, type = 'boolean')
  166.             elif key == 'Example':
  167.                 self.checkValue(key, value)
  168.             elif re.match('^X-[a-zA-Z0-9-]+', key):
  169.                 pass
  170.             else:
  171.                 self.errors.append('Invalid key: %s' % key)
  172.         elif group in self.getDirectories():
  173.             if key == 'Size':
  174.                 self.checkValue(key, value, type = 'integer')
  175.             elif key == 'Context':
  176.                 self.checkValue(key, value)
  177.             elif key == 'Type':
  178.                 self.checkValue(key, value)
  179.                 if value not in ('Fixed', 'Scalable', 'Threshold'):
  180.                     self.errors.append("Key 'Type' must be one out of 'Fixed','Scalable','Threshold', but is %s" % value)
  181.                 
  182.             elif key == 'MaxSize':
  183.                 self.checkValue(key, value, type = 'integer')
  184.                 if self.type != 'Scalable':
  185.                     self.errors.append("Key 'MaxSize' give, but Type is %s" % self.type)
  186.                 
  187.             elif key == 'MinSize':
  188.                 self.checkValue(key, value, type = 'integer')
  189.                 if self.type != 'Scalable':
  190.                     self.errors.append("Key 'MinSize' give, but Type is %s" % self.type)
  191.                 
  192.             elif key == 'Threshold':
  193.                 self.checkValue(key, value, type = 'integer')
  194.                 if self.type != 'Threshold':
  195.                     self.errors.append("Key 'Threshold' give, but Type is %s" % self.type)
  196.                 
  197.             elif re.match('^X-[a-zA-Z0-9-]+', key):
  198.                 pass
  199.             else:
  200.                 self.errors.append('Invalid key: %s' % key)
  201.         
  202.  
  203.  
  204.  
  205. class IconData(IniFile):
  206.     '''Class to parse and validate IconData Files'''
  207.     
  208.     def __init__(self):
  209.         IniFile.__init__(self)
  210.  
  211.     
  212.     def __repr__(self):
  213.         return self.getDisplayName()
  214.  
  215.     
  216.     def parse(self, file):
  217.         IniFile.parse(self, file, [
  218.             'Icon Data'])
  219.  
  220.     
  221.     def getDisplayName(self):
  222.         return self.get('DisplayName', locale = True)
  223.  
  224.     
  225.     def getEmbeddedTextRectangle(self):
  226.         return self.get('EmbeddedTextRectangle', list = True)
  227.  
  228.     
  229.     def getAttachPoints(self):
  230.         return self.get('AttachPoints', type = 'point', list = True)
  231.  
  232.     
  233.     def checkExtras(self):
  234.         if self.fileExtension != '.icon':
  235.             self.warnings.append('Unknown File extension')
  236.         
  237.  
  238.     
  239.     def checkGroup(self, group):
  240.         if not group == self.defaultGroup and re.match('^\\[X-', group) and group.encode('ascii', 'ignore') == group:
  241.             self.errors.append('Invalid Group name: %s' % group.encode('ascii', 'replace'))
  242.         
  243.  
  244.     
  245.     def checkKey(self, key, value, group):
  246.         if re.match('^DisplayName' + xdg.Locale.regex + '$', key):
  247.             pass
  248.         elif key == 'EmbeddedTextRectangle':
  249.             self.checkValue(key, value, type = 'integer', list = True)
  250.         elif key == 'AttachPoints':
  251.             self.checkValue(key, value, type = 'point', list = True)
  252.         elif re.match('^X-[a-zA-Z0-9-]+', key):
  253.             pass
  254.         else:
  255.             self.errors.append('Invalid key: %s' % key)
  256.  
  257.  
  258. icondirs = []
  259. for basedir in xdg_data_dirs:
  260.     icondirs.append(os.path.join(basedir, 'icons'))
  261.  
  262. icondirs.append('/usr/share/pixmaps')
  263. icondirs.append(os.path.expanduser('~/.icons'))
  264. themes = []
  265. cache = dict()
  266. dache = dict()
  267. eache = dict()
  268.  
  269. def getIconPath(iconname, size = None, theme = None, extensions = [
  270.     'png',
  271.     'svg',
  272.     'xpm']):
  273.     global themes
  274.     if size == None:
  275.         size = xdg.Config.icon_size
  276.     
  277.     if theme == None:
  278.         theme = xdg.Config.icon_theme
  279.     
  280.     if os.path.isabs(iconname):
  281.         return iconname
  282.     if os.path.splitext(iconname)[1][1:] in extensions:
  283.         iconname = os.path.splitext(iconname)[0]
  284.     
  285.     
  286.     try:
  287.         if themes[0].name != theme:
  288.             themes = []
  289.             __addTheme(theme)
  290.     except IndexError:
  291.         __addTheme(theme)
  292.  
  293.     tmp = ''.join([
  294.         iconname,
  295.         str(size),
  296.         theme,
  297.         ''.join(extensions)])
  298.     if eache.has_key(tmp):
  299.         if int(time.time() - eache[tmp][0]) >= xdg.Config.cache_time:
  300.             del eache[tmp]
  301.         else:
  302.             return eache[tmp][1]
  303.     int(time.time() - eache[tmp][0]) >= xdg.Config.cache_time
  304.     for thme in themes:
  305.         icon = LookupIcon(iconname, size, thme, extensions)
  306.         if icon:
  307.             eache[tmp] = [
  308.                 time.time(),
  309.                 icon]
  310.             return icon
  311.     
  312.     for directory in icondirs:
  313.         if (not dache.has_key(directory) or int(time.time() - dache[directory][1]) >= xdg.Config.cache_time or dache[directory][2] < os.path.getmtime(directory)) and os.path.isdir(directory):
  314.             dache[directory] = [
  315.                 os.listdir(directory),
  316.                 time.time(),
  317.                 os.path.getmtime(directory)]
  318.             continue
  319.         icon
  320.     
  321.     for dir, values in dache.items():
  322.         for extension in extensions:
  323.             
  324.             try:
  325.                 if iconname + '.' + extension in values[0]:
  326.                     icon = os.path.join(dir, iconname + '.' + extension)
  327.                     eache[tmp] = [
  328.                         time.time(),
  329.                         icon]
  330.                     return icon
  331.             continue
  332.             except UnicodeDecodeError:
  333.                 continue
  334.             
  335.  
  336.         
  337.     
  338.     if theme != 'hicolor':
  339.         icon = getIconPath(iconname, size, 'hicolor')
  340.         eache[tmp] = [
  341.             time.time(),
  342.             icon]
  343.         return icon
  344.  
  345.  
  346. def getIconData(path):
  347.     if os.path.isfile(path):
  348.         dirname = os.path.dirname(path)
  349.         basename = os.path.basename(path)
  350.         if os.path.isfile(os.path.join(dirname, basename + '.icon')):
  351.             data = IconData()
  352.             data.parse(os.path.join(dirname, basename + '.icon'))
  353.             return data
  354.     
  355.  
  356.  
  357. def __addTheme(theme):
  358.     for dir in icondirs:
  359.         if os.path.isfile(os.path.join(dir, theme, 'index.theme')):
  360.             __parseTheme(os.path.join(dir, theme, 'index.theme'))
  361.             break
  362.             continue
  363.         if os.path.isfile(os.path.join(dir, theme, 'index.desktop')):
  364.             __parseTheme(os.path.join(dir, theme, 'index.desktop'))
  365.             break
  366.             continue
  367.     elif debug:
  368.         raise NoThemeError(theme)
  369.     
  370.  
  371.  
  372. def __parseTheme(file):
  373.     theme = IconTheme()
  374.     theme.parse(file)
  375.     themes.append(theme)
  376.     for subtheme in theme.getInherits():
  377.         __addTheme(subtheme)
  378.     
  379.  
  380.  
  381. def LookupIcon(iconname, size, theme, extensions):
  382.     if not cache.has_key(theme.name):
  383.         cache[theme.name] = []
  384.         cache[theme.name].append(time.time() - (xdg.Config.cache_time + 1))
  385.         cache[theme.name].append(0)
  386.         cache[theme.name].append(dict())
  387.     
  388.     if int(time.time() - cache[theme.name][0]) >= xdg.Config.cache_time:
  389.         cache[theme.name][0] = time.time()
  390.         for subdir in theme.getDirectories():
  391.             for directory in icondirs:
  392.                 dir = os.path.join(directory, theme.name, subdir)
  393.                 if (not cache[theme.name][2].has_key(dir) or cache[theme.name][1] < os.path.getmtime(os.path.join(directory, theme.name))) and subdir != '' and os.path.isdir(dir):
  394.                     cache[theme.name][2][dir] = [
  395.                         subdir,
  396.                         os.listdir(dir)]
  397.                     cache[theme.name][1] = os.path.getmtime(os.path.join(directory, theme.name))
  398.                     continue
  399.             
  400.         
  401.     
  402.     for dir, values in cache[theme.name][2].items():
  403.         if DirectoryMatchesSize(values[0], size, theme):
  404.             for extension in extensions:
  405.                 if iconname + '.' + extension in values[1]:
  406.                     return os.path.join(dir, iconname + '.' + extension)
  407.             
  408.         iconname + '.' + extension in values[1]
  409.     
  410.     minimal_size = sys.maxint
  411.     closest_filename = ''
  412.     for dir, values in cache[theme.name][2].items():
  413.         distance = DirectorySizeDistance(values[0], size, theme)
  414.         if distance < minimal_size:
  415.             for extension in extensions:
  416.                 if iconname + '.' + extension in values[1]:
  417.                     closest_filename = os.path.join(dir, iconname + '.' + extension)
  418.                     minimal_size = distance
  419.                     continue
  420.             
  421.     
  422.     return closest_filename
  423.  
  424.  
  425. def DirectoryMatchesSize(subdir, iconsize, theme):
  426.     Type = theme.getType(subdir)
  427.     Size = theme.getSize(subdir)
  428.     Threshold = theme.getThreshold(subdir)
  429.     MinSize = theme.getMinSize(subdir)
  430.     MaxSize = theme.getMaxSize(subdir)
  431.     if Type == 'Fixed':
  432.         return Size == iconsize
  433.     if Type == 'Scaleable':
  434.         if iconsize <= iconsize:
  435.             return iconsize <= MaxSize
  436.         iconsize <= iconsize
  437.         return iconsize
  438.     if Type == 'Threshold':
  439.         if iconsize <= iconsize:
  440.             return iconsize <= Size + Threshold
  441.         iconsize <= iconsize
  442.         return iconsize
  443.  
  444.  
  445. def DirectorySizeDistance(subdir, iconsize, theme):
  446.     Type = theme.getType(subdir)
  447.     Size = theme.getSize(subdir)
  448.     Threshold = theme.getThreshold(subdir)
  449.     MinSize = theme.getMinSize(subdir)
  450.     MaxSize = theme.getMaxSize(subdir)
  451.     if Type == 'Fixed':
  452.         return abs(Size - iconsize)
  453.     if Type == 'Scalable':
  454.         if iconsize < MinSize:
  455.             return MinSize - iconsize
  456.         if iconsize > MaxSize:
  457.             return MaxSize - iconsize
  458.         return 0
  459.     if Type == 'Threshold':
  460.         if iconsize < Size - Threshold:
  461.             return MinSize - iconsize
  462.         if iconsize > Size + Threshold:
  463.             return iconsize - MaxSize
  464.         return 0
  465.  
  466.